<template>
  <div class="role">
    <BaseList
      title="角色列表"
      :loading="loading"
      :data="tableData"
      :search-fields="searchFields"
      :pagination="pagination"
      :debounce-delay="300"
      @search="handleSearch"
      @reset="handleReset"
      @add="handleAdd"
      @update:pagination="handlePaginationChange"
    >
      <template #columns>
        <a-table-column title="角色名称" data-index="roleName" />
        <a-table-column title="角色编码" data-index="roleCode" />
        <a-table-column title="角色描述" data-index="roleDescription" />
        <a-table-column title="状态" data-index="roleStatus">
          <template #cell="{ record }">
            <a-tag :color="record.roleStatus === 1 ? 'green' : 'red'">
              {{ record.roleStatus === 1 ? '正常' : '停用' }}
            </a-tag>
          </template>
        </a-table-column>
        <a-table-column title="创建时间" data-index="gmtCreate" />
        <a-table-column title="操作" align="center" :width="240">
          <template #cell="{ record }">
            <a-space>
              <BaseButton
                type="outline"
                size="mini"
                @click="handleDetail(record)"
                v-permission="'system:role:details'"
              >
                <template #icon>
                  <BaseIcon name="IconEye" />
                </template>
                详情
              </BaseButton>
              <BaseButton
                type="outline"
                size="mini"
                @click="handleEdit(record)"
                v-permission="'system:role:edit'"
              >
                <template #icon>
                  <BaseIcon name="IconEdit" />
                </template>
                编辑
              </BaseButton>
              <BaseButton
                type="outline"
                size="mini"
                @click="handlePermission(record)"
                v-permission="'system:role:permission'"
              >
                <template #icon>
                  <BaseIcon name="IconLock" />
                </template>
                权限
              </BaseButton>
              <BaseButton
                type="outline"
                size="mini"
                status="danger"
                :loading="loading"
                @click="handleDelete(record)"
                v-permission="'system:role:delete'"
              >
                <template #icon>
                  <BaseIcon name="IconDelete" />
                </template>
                删除
              </BaseButton>
            </a-space>
          </template>
        </a-table-column>
      </template>
    </BaseList>

    <LoadingSpinner :visible="loading" text="加载中..." />

    <!-- 添加/编辑角色弹窗 -->
    <BaseForm
      v-model:visible="dialogVisible"
      :title="dialogTitle"
      :loading="loading"
      v-model="formData"
      :rules="rules"
      @cancel="handleCancel"
      @submit="handleSubmit"
    >
      <template #form-items>
        <a-form-item
          label="角色名称"
          field="roleName"
          :label-col-props="{ span: 24 }"
          :wrapper-col-props="{ span: 24 }"
        >
          <a-input
            v-model="formData.roleName"
            placeholder="请输入角色名称"
            size="large"
            allow-clear
          />
        </a-form-item>

        <a-form-item
          label="角色编码"
          field="roleCode"
          :label-col-props="{ span: 24 }"
          :wrapper-col-props="{ span: 24 }"
        >
          <a-input
            v-model="formData.roleCode"
            placeholder="请输入角色编码"
            size="large"
            allow-clear
          />
        </a-form-item>

        <a-form-item
          label="角色描述"
          field="roleDescription"
          :label-col-props="{ span: 24 }"
          :wrapper-col-props="{ span: 24 }"
        >
          <a-textarea
            v-model="formData.roleDescription"
            placeholder="请输入角色描述"
            :auto-size="{ minRows: 3, maxRows: 5 }"
          />
        </a-form-item>

        <a-form-item
          label="状态"
          field="roleStatus"
          :label-col-props="{ span: 24 }"
          :wrapper-col-props="{ span: 24 }"
        >
          <a-radio-group v-model="formData.roleStatus" size="large">
            <a-radio :value="1">正常</a-radio>
            <a-radio :value="2">停用</a-radio>
          </a-radio-group>
        </a-form-item>
      </template>
    </BaseForm>

    <!-- 修改权限分配弹窗部分 -->
    <a-modal
      v-model:visible="permissionVisible"
      title="权限分配"
      :width="800"
      @cancel="handlePermissionCancel"
      @before-ok="handlePermissionSubmit"
    >
      <a-spin :loading="permissionLoading" class="w-full">
        <div class="flex justify-center gap-8">
          <!-- 功能权限-->
          <div class="w-[350px]">
            <div class="mb-4 text-lg font-medium">功能权限</div>
            <div class="border rounded-lg p-4 min-h-[500px] max-h-[600px] overflow-auto bg-gray-50">
              <a-tree
                v-if="transformedFeatureTree.length"
                v-model:checked-keys="checkedFeatureKeys"
                v-model:half-checked-keys="halfCheckedFeatureKeys"
                :data="transformedFeatureTree"
                checkable
                :size="'medium'"
                :auto-expand="true"
                :block-node="true"
              />
              <a-empty v-else description="暂无功能权限" />
            </div>
          </div>

          <!-- 数据权限 -->
          <div class="w-[350px]">
            <div class="mb-4 text-lg font-medium">数据权限</div>
            <div class="border rounded-lg p-4 min-h-[500px] max-h-[600px] overflow-auto bg-gray-50">
              <a-tree
                v-if="transformedRecordTree.length"
                v-model:checked-keys="checkedRecordKeys"
                v-model:half-checked-keys="halfCheckedRecordKeys"
                :data="transformedRecordTree"
                checkable
                :size="'medium'"
                :auto-expand="true"
                :block-node="true"
              />
              <a-empty v-else description="暂无数据权限" />
            </div>
          </div>
        </div>
      </a-spin>
    </a-modal>

    <!-- 详情弹窗 -->
    <a-modal v-model:visible="detailVisible" title="角色详情" :footer="false" :width="800">
      <div class="p-6">
        <!-- 基本信息区域 -->
        <div class="mb-8">
          <div class="text-lg font-medium mb-4">基本信息</div>
          <div class="grid grid-cols-2 gap-6">
            <div class="info-item">
              <div class="info-label">角色名称</div>
              <div class="info-value">{{ detailInfo.roleName || '-' }}</div>
            </div>
            <div class="info-item">
              <div class="info-label">角色编码</div>
              <div class="info-value">{{ detailInfo.roleCode || '-' }}</div>
            </div>
            <div class="info-item">
              <div class="info-label">角色描述</div>
              <div class="info-value">{{ detailInfo.roleDescription || '-' }}</div>
            </div>
            <div class="info-item">
              <div class="info-label">状态</div>
              <div class="info-value">
                <a-tag :color="detailInfo.roleStatus === 1 ? 'green' : 'red'">
                  {{ detailInfo.roleStatus === 1 ? '正常' : '停用' }}
                </a-tag>
              </div>
            </div>
          </div>
        </div>

        <!-- 权限信息区域 -->
        <div class="mb-8">
          <div class="text-lg font-medium mb-4">权限信息</div>
          <div class="flex gap-6 h-[400px]">
            <!-- 功能权限 -->
            <div class="flex-1 flex flex-col">
              <div class="mb-2 text-gray-600">功能权限</div>
              <div class="flex-1 border rounded-lg p-4 overflow-auto bg-gray-50">
                <a-tree
                  v-if="detailFeatureTree.length"
                  :data="detailFeatureTree"
                  :checkable="false"
                  :size="'medium'"
                  :auto-expand="true"
                  :block-node="true"
                />
                <a-empty v-else description="暂无功能权限" />
              </div>
            </div>

            <!-- 数据权限 -->
            <div class="flex-1 flex flex-col">
              <div class="mb-2 text-gray-600">数据权限</div>
              <div class="flex-1 border rounded-lg p-4 overflow-auto bg-gray-50">
                <a-tree
                  v-if="detailRecordTree.length"
                  :data="detailRecordTree"
                  :checkable="false"
                  :size="'medium'"
                  :auto-expand="true"
                  :block-node="true"
                />
                <a-empty v-else description="暂无数据权限" />
              </div>
            </div>
          </div>
        </div>

        <!-- 系统信息区域 -->
        <div class="bg-gray-50 rounded-lg p-4">
          <div class="text-sm text-gray-500 mb-3">系统信息</div>
          <div class="grid grid-cols-2 gap-4">
            <div class="time-item">
              <div class="time-label">创建时间</div>
              <div class="time-value">{{ detailInfo.gmtCreate || '-' }}</div>
            </div>
            <div class="time-item">
              <div class="time-label">创建人</div>
              <div class="time-value">{{ detailInfo.gmtCreateName || '-' }}</div>
            </div>
            <div class="time-item">
              <div class="time-label">更新时间</div>
              <div class="time-value">{{ detailInfo.gmtModified || '-' }}</div>
            </div>
            <div class="time-item">
              <div class="time-label">更新人</div>
              <div class="time-value">{{ detailInfo.gmtModifiedName || '-' }}</div>
            </div>
          </div>
        </div>
      </div>
    </a-modal>
  </div>
</template>

<script setup lang="ts" name="SystemRole">
import { ref, reactive } from 'vue'
import BaseList from '@/components/BaseList.vue'
import LoadingSpinner from '@/components/LoadingSpinner.vue'
import { useNotification } from '@/composables/useNotification'
import { filterEmptyValue } from '@/utils/object'
import BaseButton from '@/components/BaseButton.vue'
import type { FormInstance } from '@arco-design/web-vue'
import { Modal } from '@arco-design/web-vue'
import BaseForm from '@/components/BaseForm.vue'
import { roleService } from '@/services/systemRole'
import type {
  RoleResponse,
  RoleRequest,
  RolePageParam,
  PermissionRecordTreeResponse,
  PermissionFeatureTreeResponse,
  RolePermissionRequest,
} from '@/types/systemRole'
import { getIcon } from '@/composables/useIcons'
import BaseIcon from '@/components/BaseIcon.vue'
import type { TreeNodeData } from '@arco-design/web-vue'

const loading = ref(false)
const tableData = ref<RoleResponse[]>([])
const notify = useNotification()

// 定义搜索字段
const searchFields = [
  {
    key: 'roleName',
    placeholder: '请输入角色名称',
    icon: getIcon('IconSearch'),
  },
  {
    key: 'roleCode',
    placeholder: '请输入角色编码',
    icon: getIcon('IconSearch'),
  },
  {
    key: 'roleStatus',
    placeholder: '请选择状态',
    type: 'select',
    options: [
      { label: '正常', value: 1 },
      { label: '停用', value: 2 },
    ],
  },
]

// 分页信息
const pagination = ref({
  total: 0,
  current: 1,
  pageSize: 10,
})

// 表单相关
const formRef = ref<FormInstance>()
const dialogVisible = ref(false)
const dialogTitle = ref('新增角色')
const isAdd = ref(true)

// 表单数据
const formData = reactive<RoleRequest>({
  roleId: '',
  roleName: '',
  roleCode: '',
  roleDescription: '',
  roleStatus: 1,
})

// 表单校验规则
const rules = {
  roleName: [{ required: true, message: '请输入角色名称' }],
  roleCode: [{ required: true, message: '请输入角色编码' }],
  roleStatus: [{ required: true, message: '请选择状态' }],
}

// 权限相关
const permissionVisible = ref(false)
const permissionLoading = ref(false)
const currentRoleId = ref('')
const transformedFeatureTree = ref<TreeNodeData[]>([])
const transformedRecordTree = ref<TreeNodeData[]>([])
const checkedFeatureKeys = ref<string[]>([])
const halfCheckedFeatureKeys = ref<string[]>([])
const checkedRecordKeys = ref<string[]>([])
const halfCheckedRecordKeys = ref<string[]>([])

// 详情相关
const detailVisible = ref(false)
const detailInfo = ref<Partial<RoleResponse>>({})
const detailFeatureTree = ref<TreeNodeData[]>([])
const detailRecordTree = ref<TreeNodeData[]>([])

// 保存当前搜索条件
const currentSearchParams = ref<Partial<RolePageParam>>({})

/** 获取角色表数据 */
const fetchData = async (searchParams: Partial<RolePageParam> = {}) => {
  loading.value = true
  try {
    const params: RolePageParam = {
      pageNum: pagination.value.current,
      pageSize: pagination.value.pageSize,
      ...filterEmptyValue(searchParams),
    }
    const res = await roleService.getRolePage(params)
    tableData.value = res.list
    pagination.value = {
      ...pagination.value,
      current: res.pageNum,
      total: res.total,
      pageSize: res.pageSize,
    }
  } catch (err) {
    const errorMessage = err instanceof Error ? err.message : '获取角色列表失败'
    notify.error(errorMessage)
    console.error('获取角色列表出错:', err)
  } finally {
    loading.value = false
  }
}

/** 搜索处理 */
const handleSearch = (form: Partial<RolePageParam>) => {
  pagination.value.current = 1
  currentSearchParams.value = form // 保存搜索条件
  fetchData(form)
}

/** 重置处理 */
const handleReset = () => {
  pagination.value.current = 1
  fetchData()
}

/** 新增角色 */
const handleAdd = () => {
  dialogVisible.value = true
  dialogTitle.value = '新增角色'
  isAdd.value = true
  resetForm()
}

/** 编辑角色 */
const handleEdit = async (record: RoleResponse) => {
  try {
    loading.value = true
    const res = await roleService.getRoleById(record.roleId)
    dialogVisible.value = true
    dialogTitle.value = '编辑角色'
    isAdd.value = false
    Object.assign(formData, res)
  } catch (err) {
    const errorMessage = err instanceof Error ? err.message : '获取角色详情失败'
    notify.error(errorMessage)
  } finally {
    loading.value = false
  }
}

/** 删除角色 */
const handleDelete = (record: RoleResponse) => {
  Modal.warning({
    title: '确认删除',
    content: `确定要删除角色 "${record.roleName}" 吗？`,
    okText: '确定',
    cancelText: '取消',
    hideCancel: false,
    async onOk() {
      try {
        loading.value = true
        await roleService.deleteRole(record.roleId)
        notify.success('删除角色成功')
        fetchData()
      } catch (err) {
        const errorMessage = err instanceof Error ? err.message : '删除角色失败'
        notify.error(errorMessage)
      } finally {
        loading.value = false
      }
    },
  })
}

/** 提交表单 */
const handleSubmit = async () => {
  try {
    loading.value = true
    if (isAdd.value) {
      await roleService.createRole(formData)
      notify.success('新增角色成功')
    } else {
      await roleService.modifyRole(formData)
      notify.success('修改角色成功')
    }
    dialogVisible.value = false
    fetchData()
    return true
  } catch (err) {
    const errorMessage =
      err instanceof Error ? err.message : `${isAdd.value ? '新增' : '修改'}角色失败`
    notify.error(errorMessage)
    return false
  } finally {
    loading.value = false
  }
}

/** 取消操作 */
const handleCancel = () => {
  dialogVisible.value = false
  resetForm()
}

/** 重置表单 */
const resetForm = () => {
  formRef.value?.resetFields()
  Object.assign(formData, {
    roleId: '',
    roleName: '',
    roleCode: '',
    roleDescription: '',
    roleStatus: 1,
  })
}

/** 分页变化处理 */
const handlePaginationChange = (newPagination: typeof pagination.value) => {
  pagination.value = newPagination
  fetchData(currentSearchParams.value) // 使用保存的搜索条件
}

/** 转换树形数据结构 */
const transformTreeData = (
  data: (PermissionFeatureTreeResponse | PermissionRecordTreeResponse)[],
): TreeNodeData[] => {
  return data.map((node) => {
    // 使用类型守卫来区分两种类型
    const isFeatureNode = (
      node: PermissionFeatureTreeResponse | PermissionRecordTreeResponse,
    ): node is PermissionFeatureTreeResponse => {
      return 'permissionName' in node
    }

    const transformed: TreeNodeData = {
      key: node.permissionId,
      title: isFeatureNode(node) ? node.permissionName : node.recordName,
      children: node.children ? transformTreeData(node.children) : undefined,
    }
    return transformed
  })
}

/**
 * 检查节点的选中状态
 * @param node 当前节点
 * @param checkedCodes 已选中的权限码
 * @returns [isChecked, isHalfChecked] 是否选中和是否半选
 */
const checkNodeStatus = (
  node: PermissionFeatureTreeResponse | PermissionRecordTreeResponse,
  checkedCodes: string[],
): [boolean, boolean] => {
  const isFeatureNode = 'permissionCode' in node

  // 如果没有子节点，直接判断当前节点
  if (!node.children?.length) {
    const isChecked = isFeatureNode
      ? checkedCodes.includes(node.permissionCode)
      : checkedCodes.includes(node.recordId)
    return [isChecked, false]
  }

  // 递归检查子节点状态
  const childrenStatus: [boolean, boolean][] = node.children.map((child) =>
    checkNodeStatus(child, checkedCodes),
  )

  // 计算选中状态
  const allChecked = childrenStatus.every(([checked]) => checked)
  const someChecked = childrenStatus.some(([checked]) => checked)
  const hasHalfChecked = childrenStatus.some(([, half]) => half)

  // 全部选中 -> 选中
  // 部分选中或子节点有半选 -> 半选
  // 都未选中 -> 未选中
  return [allChecked, !allChecked && (someChecked || hasHalfChecked)]
}

/** 初始化权限树选中状态 */
const initTreeCheckedStatus = (
  tree: (PermissionFeatureTreeResponse | PermissionRecordTreeResponse)[],
  checkedCodes: string[],
) => {
  const checkedKeys: string[] = []
  const halfCheckedKeys: string[] = []

  const traverse = (nodes: (PermissionFeatureTreeResponse | PermissionRecordTreeResponse)[]) => {
    nodes.forEach((node) => {
      const [isChecked, isHalfChecked] = checkNodeStatus(node, checkedCodes)

      if (isChecked) {
        checkedKeys.push(node.permissionId)
      } else if (isHalfChecked) {
        halfCheckedKeys.push(node.permissionId)
      }

      if (node.children?.length) {
        traverse(node.children)
      }
    })
  }

  traverse(tree)
  return [checkedKeys, halfCheckedKeys]
}

/** 打开权限弹窗 */
const handlePermission = async (record: RoleResponse) => {
  try {
    permissionVisible.value = true
    permissionLoading.value = true
    currentRoleId.value = record.roleId

    const [res, permissionCodeRes] = await Promise.all([
      roleService.getRolePermission(),
      roleService.getPermissionCodesByRoleId(record.roleId),
    ])

    transformedFeatureTree.value = transformTreeData(res.permissionFeatureTreeList || [])
    transformedRecordTree.value = transformTreeData(res.permissionRecordTreeList || [])

    // 初始化功能权限选中状态
    const [featureChecked, featureHalfChecked] = initTreeCheckedStatus(
      res.permissionFeatureTreeList || [],
      permissionCodeRes.permissionFeatureRermissionCodeList || [],
    )
    checkedFeatureKeys.value = featureChecked
    halfCheckedFeatureKeys.value = featureHalfChecked

    // 初始化数据权限选中状态
    const [recordChecked, recordHalfChecked] = initTreeCheckedStatus(
      res.permissionRecordTreeList || [],
      permissionCodeRes.permissionRecordRecordIdList || [],
    )
    checkedRecordKeys.value = recordChecked
    halfCheckedRecordKeys.value = recordHalfChecked
  } catch (err) {
    const errorMessage = err instanceof Error ? err.message : '获取权限信息失败'
    notify.error(errorMessage)
  } finally {
    permissionLoading.value = false
  }
}

/** 提交权限分配 */
const handlePermissionSubmit = async () => {
  try {
    permissionLoading.value = true
    const params: RolePermissionRequest = {
      roleId: currentRoleId.value,
      permissionFeatureIds: [...checkedFeatureKeys.value, ...halfCheckedFeatureKeys.value],
      permissionRecordIds: [...checkedRecordKeys.value, ...halfCheckedRecordKeys.value],
    }
    await roleService.bindRolePermission(params)
    notify.success('权限分配成功')
    permissionVisible.value = false
    return true
  } catch (err) {
    const errorMessage = err instanceof Error ? err.message : '权限分配失败'
    notify.error(errorMessage)
    return false
  } finally {
    permissionLoading.value = false
  }
}

/** 取消权限分配 */
const handlePermissionCancel = () => {
  permissionVisible.value = false
  currentRoleId.value = ''
  checkedFeatureKeys.value = []
  halfCheckedFeatureKeys.value = []
  checkedRecordKeys.value = []
  halfCheckedRecordKeys.value = []
}

/** 查看详情 */
const handleDetail = async (record: RoleResponse) => {
  try {
    loading.value = true
    const [roleDetail, permissionDetail, permissionCodeRes] = await Promise.all([
      roleService.getRoleById(record.roleId),
      roleService.getRolePermission(),
      roleService.getPermissionCodesByRoleId(record.roleId),
    ])

    // 更新详情数据
    detailInfo.value = roleDetail

    // 转换权限树数据并根据已分配的权限过滤
    const featureTree = permissionDetail.permissionFeatureTreeList || []
    const recordTree = permissionDetail.permissionRecordTreeList || []

    // 过滤功能权限树
    const [featureChecked] = initTreeCheckedStatus(
      featureTree,
      permissionCodeRes.permissionFeatureRermissionCodeList || [],
    )
    detailFeatureTree.value = filterTreeByCheckedKeys(
      transformTreeData(featureTree),
      featureChecked,
    )

    // 过滤数据权限树
    const [recordChecked] = initTreeCheckedStatus(
      recordTree,
      permissionCodeRes.permissionRecordRecordIdList || [],
    )
    detailRecordTree.value = filterTreeByCheckedKeys(transformTreeData(recordTree), recordChecked)

    detailVisible.value = true
  } catch (err) {
    const errorMessage = err instanceof Error ? err.message : '获取角色详情失败'
    notify.error(errorMessage)
  } finally {
    loading.value = false
  }
}

/** 根据选中的key过滤树形数据 */
const filterTreeByCheckedKeys = (tree: TreeNodeData[], checkedKeys: string[]): TreeNodeData[] => {
  return tree
    .map((node) => {
      // 如果当前节点被选中,保留该节点
      if (checkedKeys.includes(node.key as string)) {
        const filteredNode = { ...node }
        // 如果有子节点,递归过滤
        if (node.children?.length) {
          filteredNode.children = filterTreeByCheckedKeys(node.children, checkedKeys)
        }
        return filteredNode
      }
      // 如果当前节点未被选中,但有子节点
      if (node.children?.length) {
        const filteredChildren = filterTreeByCheckedKeys(node.children, checkedKeys)
        // 如果过滤后的子节点不为空,保留该父节点
        if (filteredChildren.length > 0) {
          return {
            ...node,
            children: filteredChildren,
          }
        }
      }
      // 其他情况返回null,后续会被过滤掉
      return null
    })
    .filter((node): node is TreeNodeData => node !== null)
}

// 初始加载
fetchData()
</script>
